package site.lanmushan.framework.mapper.wrapper;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.*;
import org.springframework.util.StringUtils;
import site.lanmushan.framework.mapper.params.SlashAndExpression;
import site.lanmushan.framework.mapper.params.SlashExpression;
import site.lanmushan.framework.mapper.params.SlashExpressionValue;
import site.lanmushan.framework.mapper.params.SlashOrExpression;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author Administrator
 */
@Data
@Slf4j
public abstract class AbstractQueryWrapper extends AbstractFormatQueryWrapper implements QueryWrapper {

    public AbstractQueryWrapper() {
    }

    public AbstractQueryWrapper(String tableName) {
        super(tableName);
    }

    public AbstractQueryWrapper(String tableName, String alias) {
        super(tableName, alias);
    }

    public AbstractQueryWrapper(Class tClass) {
        super(tClass);
    }

    public AbstractQueryWrapper(Class tClass, String alias) {
        super(tClass, alias);
    }

    protected void andExpression(Expression expression) {
        if (this.expression == null) {
            this.expression = expression;
        } else {
            this.expression = new AndExpression(this.expression, expression);
        }
    }

    protected void orExpression(Expression expression) {
        if (this.expression == null) {
            this.expression = expression;
        } else {
            this.expression = new OrExpression(this.expression, expression);
        }
    }

    @Override
    public void setAlias(String alias) {
        this.alias = alias;
    }

    @Override
    public QueryWrapper column(String... columns) {
        this.columns.addAll(Arrays.asList(columns));
        return this;
    }

    @Override
    public QueryWrapper sum(String column) {
        return null;
    }

    @Override
    public QueryWrapper max(String column) {
        return null;
    }

    @Override
    public QueryWrapper count(String column) {
        return null;
    }

    @Override
    public QueryWrapper eq(String column, Object... values) {
        SlashExpression slashExpression = new SlashOrExpression();
        values = Arrays.stream(values).filter(Objects::nonNull).collect(Collectors.toList()).toArray();
        for (Object value : values) {
            EqualsTo equalsTo = new EqualsTo();
            equalsTo.setLeftExpression(createColumn(column));
            equalsTo.setRightExpression(new SlashExpressionValue(value));
            slashExpression.addExpression(equalsTo);
        }
        this.andExpression(slashExpression);
        return this;
    }

    @Override
    public QueryWrapper or(String column, Object... values) {
        SlashExpression slashExpression = new SlashOrExpression();
        values = Arrays.stream(values).filter(Objects::nonNull).collect(Collectors.toList()).toArray();
        for (Object value : values) {
            EqualsTo equalsTo = new EqualsTo();
            equalsTo.setLeftExpression(createColumn(column));
            equalsTo.setRightExpression(new SlashExpressionValue(value));
            slashExpression.addExpression(equalsTo);
        }
        this.orExpression(slashExpression);
        return this;
    }

    @Override
    public QueryWrapper orLike(List<String> columns, String value) {
        if (StringUtils.isEmpty(value)) {
            return this;
        }
        SlashExpression slashExpression = new SlashOrExpression();
        for (String column : columns) {
            LikeExpression likeExpression = new LikeExpression();
            likeExpression.setLeftExpression(createColumn(column));
            likeExpression.setRightExpression(new SlashExpressionValue("%" + value + "%"));
            slashExpression.addExpression(likeExpression);
        }
        this.andExpression(slashExpression);
        return this;
    }

    @Override
    public QueryWrapper orLeftLike(List<String> columns, String value) {
        if (StringUtils.isEmpty(value)||columns==null||columns.isEmpty()) {
            return this;
        }
        SlashExpression slashExpression = new SlashOrExpression();
        for (String column : columns) {
            LikeExpression likeExpression = new LikeExpression();
            likeExpression.setLeftExpression(createColumn(column));
            likeExpression.setRightExpression(new SlashExpressionValue(value + "%"));
            slashExpression.addExpression(likeExpression);
        }
        this.andExpression(slashExpression);
        return this;
    }

    @Override
    public QueryWrapper orRightLike(List<String> columns, String value) {
        if (StringUtils.isEmpty(value)||columns==null||columns.isEmpty()) {
            return this;
        }
        SlashExpression slashExpression = new SlashOrExpression();
        for (String column : columns) {
            LikeExpression likeExpression = new LikeExpression();
            likeExpression.setLeftExpression(createColumn(column));
            likeExpression.setRightExpression(new SlashExpressionValue("%" + value));
            slashExpression.addExpression(likeExpression);
        }
        this.andExpression(slashExpression);
        return this;
    }

    @Override
    public QueryWrapper notEq(String column, Object... values) {
        values = Arrays.stream(values).filter(Objects::nonNull).collect(Collectors.toList()).toArray();
        if (values.length == 0) {
            return this;
        }
        SlashExpression slashExpression = new SlashOrExpression();
        for (Object value : values) {
            NotEqualsTo equalsTo = new NotEqualsTo();
            equalsTo.setLeftExpression(createColumn(column));
            equalsTo.setRightExpression(new SlashExpressionValue(value));
            slashExpression.addExpression(equalsTo);
        }
        this.andExpression(slashExpression);
        return this;
    }

    @Override
    public QueryWrapper gt(String column, Object... values) {
        values = Arrays.stream(values).filter(Objects::nonNull).collect(Collectors.toList()).toArray();
        if (values.length == 0) {
            return this;
        }
        SlashExpression slashExpression = new SlashAndExpression();
        for (Object value : values) {
            MinorThan equalsTo = new MinorThan();
            equalsTo.setLeftExpression(createColumn(column));
            equalsTo.setRightExpression(new SlashExpressionValue(value));
            slashExpression.addExpression(equalsTo);
        }
        this.andExpression(slashExpression);
        return this;
    }

    @Override
    public QueryWrapper gte(String column, Object... values) {
        values = Arrays.stream(values).filter(Objects::nonNull).collect(Collectors.toList()).toArray();
        if (values.length == 0) {
            return this;
        }
        SlashExpression slashExpression = new SlashAndExpression();

        for (Object value : values) {
            GreaterThanEquals equalsTo = new GreaterThanEquals();
            equalsTo.setLeftExpression(createColumn(column));
            equalsTo.setRightExpression(new SlashExpressionValue(value));
            slashExpression.addExpression(equalsTo);
        }
        this.andExpression(slashExpression);
        return this;
    }

    @Override
    public QueryWrapper lt(String column, Object... values) {
        values = Arrays.stream(values).filter(Objects::nonNull).collect(Collectors.toList()).toArray();
        if (values.length == 0) {
            return this;
        }
        SlashExpression slashExpression = new SlashAndExpression();
        for (Object value : values) {
            MinorThan equalsTo = new MinorThan();
            equalsTo.setLeftExpression(createColumn(column));
            equalsTo.setRightExpression(new SlashExpressionValue(value));
            slashExpression.addExpression(equalsTo);
        }
        this.andExpression(slashExpression);
        return this;
    }

    @Override
    public QueryWrapper lte(String column, Object... values) {
        values = Arrays.stream(values).filter(Objects::nonNull).collect(Collectors.toList()).toArray();
        if (values.length == 0) {
            return this;
        }
        SlashExpression slashExpression = new SlashOrExpression();
        for (Object value : values) {
            MinorThanEquals equalsTo = new MinorThanEquals();
            equalsTo.setLeftExpression(createColumn(column));
            equalsTo.setRightExpression(new SlashExpressionValue(value));
            slashExpression.addExpression(equalsTo);
        }
        this.andExpression(slashExpression);
        return this;
    }

    @Override
    public QueryWrapper like(String column, Object... values) {
        values = Arrays.stream(values).filter(Objects::nonNull).collect(Collectors.toList()).toArray();
        if (values.length == 0) {
            return this;
        }
        SlashExpression slashExpression = new SlashOrExpression();
        for (Object value : values) {
            LikeExpression likeExpression = new LikeExpression();
            likeExpression.setLeftExpression(createColumn(column));
            likeExpression.setRightExpression(new SlashExpressionValue("%" + value + "%"));
            slashExpression.addExpression(likeExpression);
        }
        this.andExpression(slashExpression);
        return this;
    }

    @Override
    public QueryWrapper leftLike(String column, Object... values) {
        values = Arrays.stream(values).filter(Objects::nonNull).collect(Collectors.toList()).toArray();
        if (values.length == 0) {
            return this;
        }
        SlashExpression slashExpression = new SlashOrExpression();
        for (Object value : values) {
            LikeExpression likeExpression = new LikeExpression();
            likeExpression.setLeftExpression(createColumn(column));
            likeExpression.setRightExpression(new SlashExpressionValue(value + "%"));
            slashExpression.addExpression(likeExpression);
        }
        this.andExpression(slashExpression);
        return this;
    }

    @Override
    public QueryWrapper rightLike(String column, Object... values) {
        values = Arrays.stream(values).filter(Objects::nonNull).collect(Collectors.toList()).toArray();
        if (values.length == 0) {
            return this;
        }
        SlashExpression slashExpression = new SlashOrExpression();
        for (Object value : values) {
            LikeExpression likeExpression = new LikeExpression();
            likeExpression.setLeftExpression(createColumn(column));
            likeExpression.setRightExpression(new SlashExpressionValue("%" + value));
            slashExpression.addExpression(likeExpression);
        }
        this.andExpression(slashExpression);
        return this;
    }

    @Override
    public QueryWrapper in(String column, Object... values) {
        values = Arrays.stream(values).filter(Objects::nonNull).collect(Collectors.toList()).toArray();
        if (values.length == 0) {
            return this;
        }
        InExpression inExpression = new InExpression();
        inExpression.setLeftExpression(createColumn(column));
        List<Expression> expressions = new ArrayList<>();
        for (Object value : values) {
            expressions.add(new SlashExpressionValue(value));
        }
        MultiExpressionList multiExpressionList = new MultiExpressionList();
        multiExpressionList.addExpressionList(expressions);
        inExpression.setRightItemsList(multiExpressionList);
        this.andExpression(inExpression);
        return this;
    }

    @Override
    public QueryWrapper in(QueryWrapper queryWrapper) {
        return null;
    }

    @Override
    public QueryWrapper notIn(String column, Object... values) {
        InExpression inExpression = new InExpression();
        inExpression.setLeftExpression(createColumn(column));
        inExpression.setNot(true);
        MultiExpressionList multiExpressionList = new MultiExpressionList();
        for (Object value : values) {
            multiExpressionList.addExpressionList(new SlashExpressionValue(value));

        }
        inExpression.setMultiExpressionList(new MultiExpressionList());
        this.andExpression(inExpression);
        return this;
    }

    @Override
    public QueryWrapper notIn(QueryWrapper queryWrapper) {
        return null;
    }

    @Override
    public QueryWrapper and(QueryWrapper queryWrapper) {
        return null;
    }

    @Override
    public QueryWrapper or(QueryWrapper queryWrapper) {
        return null;
    }

    @Override
    public QueryWrapper groupBy(String... columns) {
        return null;
    }

    @Override
    public QueryWrapper orderBy(String orderBy) {
        return null;
    }

    @Override
    public QueryWrapper exists(String exists) {
        return null;
    }


}
